import router, { dynamicRouter, staticRouter } from '@/router/index'
import { getToken } from "@/utils/token"
import { useUserStore } from "@/stores"
import { getUserInfoApi } from '@/api/user'
// 引入vue-router 内置数据类型 防止编辑器报错
import type { RouteRecordRaw } from 'vue-router';
// 深拷贝函数
import { copyFn } from "@/utils/processing"

//定义路由白名单
const Whitelist = ['/', '/login', '/404']

router.beforeEach(async (to, from, next) => {
    const userStore = useUserStore()
    const token = getToken()
    if (token) {
        if (to.path === '/login') next('/home')
        else if (!userStore.userInfo) {
            // 获取用户信息
            const res = await getUserInfoApi()

            // 用户权限存pinia 不作持久化处理 防止手动更改
            userStore.setUserInfo(res.result)
            // role: 用户权限字段
            const { role } = res.result


            // 动态路由中component字段为函数JSON.parse，json.stringify无法实现深拷贝
            // 如果路由数据由后端提供， 无需此操作
            const dynamic_router = copyFn(dynamicRouter)

            // 递归动态路由
            const routers = routerFilter(dynamic_router, role)

            // pinia 存储
            userStore.setUserRouter([...staticRouter, ...routers])

            // 路由添加 addRoutes以弃用
            routers.forEach(v => {
                router.addRoute(v)
            })
            // router.getRoutes()查看结果


            // 首次或者刷新界面，next(...to, replace: true)会循环遍历路由，
            // 如果to找不到对应的路由那么他会再执行一次beforeEach((to, from, next))直到找到对应的路由，
            // 我们的问题在于页面刷新以后获取数据，直接执行next()感觉路由添加了,但是 是在next()之后执行的，所以我们没法导航到相应的界面。
            // next()
            next({ ...to, replace: true })

        } else next()
    } else {
        if (!Whitelist.includes(to.path)) next('/login')
        else next()
    }
})

//递归查询函数
const routerFilter = (route_list: RouteRecordRaw[], role: number): RouteRecordRaw[] => {
    // role === 0拥有所有权限 dynamicRouter定义的动态路由
    if (role === 0) return dynamicRouter

    // 有children字段 ？ 递归查询 ： 权限判断
    const routes = route_list.filter(v => {
        if (v.children) {
            //  这一步操作会更改原数组，所以对动态路由进行了深拷贝处理
            v.children = routerFilter(v.children, role)
        }
        // 没有定义roles字段表示所有用户都能访问
        return !v.meta?.roles || (v.meta.roles as number[]).includes(role)
    })
    // 返回路由列表
    return routes
}
